/* $Id:person_items.cc $ */
/*
   Copyright (C) 2007 by Jurjen Stellingwerff <jurjen@stwerff.xs4all.nl>
   Part of the Moros Project http://moros.sourceforge.net/

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License version 3.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY.

   See the COPYING file for more details.
*/

#define DEBUG_ROUTINE "person_items"

#include <sstream>
#include <fstream>
#include "../general/util.h"
#include "../general/log.h"
#include "../general/channel.h"
#include "person_items.h"
#include "item.h"
#include "stat.h"
#include "person.h"
#include "../general/general.h"

person_items::person_items() {
    type=0;
    damage=0;
    stats=map<string,class stat_amount>();
    usage=map<int,class action_level>();
    maxUsage=0;
    points=0;
    position=0;
    owner=0;
}

// Field : type

class item& person_items::getType() const { if (type==0) throw nullpointer(); return *type; }
void person_items::setType(class item &v) { type=&v; }

// Field : damage

const int person_items::getDamage() const { return damage; }
void person_items::setDamage(const int v) { damage=v; }

// Field : stats

class stat_amount& person_items::getStats(const string v) { return stats[v]; }
map<string,class stat_amount>& person_items::listStats() { return stats; }
void person_items::setStats(class stat_amount &v) {
    stats[v.getStat().getName()]=v;
}
void person_items::delStats(const string v) { stats.erase(v); }
const bool person_items::isStats(const string v) const { return stats.count(v)>0; }

// Field : usage

class action_level& person_items::getUsage(const int v) { return usage[v]; }
map<int,class action_level>& person_items::listUsage() { return usage; }
void person_items::setUsage(class action_level &v) {
    if (v.getNr()==0) v.setNr(++maxUsage);
    usage[v.getNr()]=v;
}
void person_items::delUsage(const int v) { usage.erase(v); }
const bool person_items::isUsage(const int v) const { return usage.count(v)>0; }

// Field : points

const int person_items::getPoints() const { return points; }
void person_items::setPoints(const int v) { points=v; }

// Field : position

const int person_items::getPosition() const { return position; }
void person_items::setPosition(const int  v) { position=v; }
const string person_items::showPosition() const {
    stringstream res;
    res << "(" << (position & 0xffff) << "," << (position << 16) << ")";
    return res.str();
}

// Field : owner

class person& person_items::getOwner() const { if (owner==0) throw nullpointer(); return *owner; }
void person_items::setOwner(class person &v) { owner=&v; }
int person_items::operator<(const class person_items &ck) const {
    return (getType().getNr() < ck.getType().getNr())?1:0;
}

void person_items::save(class channel &ch) {
    ch.write("person_items", "");
    ch.write("t", getType().getName());
    ch.write("d", getDamage());
    loopPerson_itemsStats(this, s_stats) {
        s_stats->save(ch);
    }
    loopPerson_itemsUsage(this, s_usage) {
        s_usage->save(ch);
    }
    ch.write("p", getPoints());
    ch.write("po", getPosition());
    ch.write("o", getOwner().getName());
}

void person_items::load(class channel &ch) {
    if (ch.key=="t" || ch.key=="type") {
        if (!item_repo.isItem(ch.value)) {
            dbg_state("link unknown item %s", ch.value.c_str());
            class item rec;
            rec.setName(ch.value);
            item_repo.setItem(rec);
            rec.setNr(0);
        }
        setType(item_repo.getItem(ch.value));
        ch.next();
    }
    if (ch.key=="d" || ch.key=="damage") { setDamage(atoi(ch.value.c_str())); ch.next(); }
    while (ch.key=="stat_amount" || ch.key=="stats") {
        ch.next();
        class stat_amount rec;
        rec.load(ch);
        setStats(rec);
    }
    while (ch.key=="action_level" || ch.key=="usage") {
        ch.next();
        class action_level rec;
        rec.load(ch);
        setUsage(rec);
    }
    if (ch.key=="p" || ch.key=="points") { setPoints(atoi(ch.value.c_str())); ch.next(); }
    if (ch.key=="po" || ch.key=="position") { setPosition(atoi(ch.value.c_str())); ch.next(); }
    if (ch.key=="o" || ch.key=="owner") {
        if (!person_repo.isPerson(ch.value)) {
            dbg_state("link unknown person %s", ch.value.c_str());
            class person rec;
            rec.setName(ch.value);
            person_repo.setPerson(rec);
        }
        setOwner(person_repo.getPerson(ch.value));
        ch.next();
    }
}

void person_items::xml(ofstream &f, int l, int r) {
    f << ncpy(l, "  ") << "<person_items damage=\"" << getDamage() <<
    "\" points=\"" << getPoints() <<
    "\" position_x=\"" << (getPosition() & 0xffff) <<
    "\" position_y=\"" << (getPosition() << 16) <<
    "\">" << endl;
    if (r<2) try {
        getType().xml(f,l+1,r+1);
        getOwner().xml(f,l+1,r+1);
    } catch (nullpointer n) {}
    if (r==0) {
        loopPerson_itemsStats(this, s_stats) {
            s_stats->xml(f,l+1);
        }
        loopPerson_itemsUsage(this, s_usage) {
            s_usage->xml(f,l+1);
        }
    }
    f << ncpy(l, "  ") << "</person_items>" << endl;
}
